package cn.lysj.framework.common.validate;

import cn.hutool.core.util.ReflectUtil;
import cn.lysj.framework.common.config.DateConverterConfig;
import cn.lysj.framework.common.utils.web.ParamUtil;
import cn.lysj.framework.common.validate.annotation.Validator;
import cn.lysj.framework.common.validate.entity.Medusa;
import cn.lysj.framework.common.validate.exception.ValidatorException;
import cn.lysj.framework.common.validate.param.Param;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @author ww
 * @description 自定义参数解析器
 * @create 2018-08-16 18:21
 **/
@Slf4j
public class ValidatorResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private DateConverterConfig dateConverterConfig;

    /**
     * @author ww
     * @date 2018-08-19 19:35
     * @Description 用于判定是否需要处理该参数，返回true为需要，并会去调用下面的方法resolveArgument
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Validator.class);
    }

    /**
     * @author ww
     * @date 2018-08-19 19:36
     * @Description 真正用于处理参数分解的方法，返回的Object就是controller方法上的形参对象
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        //获取参数的class
        Class clazz = parameter.getParameterType();
        //实例化参数对象
        Object object = BeanUtils.instantiate(clazz);
        //获取对象中所有的成员变量，包括父类中的成员变量
        Field[] fields = ReflectUtil.getFields(clazz);
        for (Field field : fields) {
            String paramName = field.getName();
            //将成员变量带入到请求中获取值
            String[] arg = webRequest.getParameterValues(paramName);
            if (arg != null && arg.length == 1) {
                String value = arg[0];
                //如果参数中有ID，则记录下来
                if(paramName.equals(Param.ID)){
                    Message.id = value;
                }
                setValue(field,field.getType().getName(),value,object);
            }
        }
        Medusa medusa = Message.getMsg(object,parameter.getParameterAnnotation(Validator.class).value());
        if(!medusa.isFlag()){
            log.error("["+clazz.getSimpleName()+"]"+medusa.getMessage());
            throw new ValidatorException(medusa.getMessage());
        }
        return object;
    }

    /**
     * @author ww
     * @date 2018-08-19 15:03
     * @Description 将值设置到对应的参数中去
     * @param field 参数对象
     * @param type 参数类型
     * @param value 参数类型
     * @param object 参数所在的类
     */
    private void setValue(Field field, String type, String value,Object object){
        field.setAccessible(true);//可以忽略访问权限的限制：比如private
        if(type.equals(String.class.getName())){
            try {
                field.set(object, value);
            }catch (Exception e){
                log.error("String类型转换错误["+value+"]");
                throw new ValidatorException("String类型转换错误["+value+"]");
            }
        } else if(type.equals(BigDecimal.class.getName())){
            try {
                if(ParamUtil.isBlank(value)){
                    value = "0";
                }
                field.set(object, new BigDecimal(value));
            }catch (Exception e){
                log.error("BigDecimal类型转换错误["+value+"]");
                throw new ValidatorException("BigDecimal类型转换错误["+value+"]");
            }
        } else if(type.equals(Integer.class.getName()) || type.equals(int.class.getName()) ){
            try {
                if(ParamUtil.isBlank(value)){
                    value = "0";
                }
                field.set(object, Integer.parseInt(value));
            }catch (Exception e){
                log.error("Integer类型转换错误["+value+"]");
                throw new ValidatorException("Integer类型转换错误["+value+"]");
            }
        } else if(type.equals(Long.class.getName()) || type.equals(long.class.getName())){
            try {
                if(ParamUtil.isBlank(value)){
                    value = "0";
                }
                field.set(object, Long.parseLong(value));
            }catch (Exception e){
                log.error("Long类型转换错误["+value+"]");
                throw new ValidatorException("Long类型转换错误["+value+"]");
            }
        }else if(type.equals(Date.class.getName())){
            try {
                field.set(object, dateConverterConfig.convert(value));
            }catch (Exception e){
                log.error("Date类型转换错误["+value+"]");
                throw new ValidatorException("Date类型转换错误["+value+"]");
            }
        }else if(type.equals(boolean.class.getName()) || type.equals(Boolean.class.getName())){
            try {
                if(ParamUtil.isBlank(value)){
                    value = "false";
                }
                field.set(object, Boolean.valueOf(value));
            }catch (Exception e){
                log.error("boolean类型转换错误["+value+"]");
                throw new ValidatorException("boolean类型转换错误["+value+"]");
            }
        }
    }

    //首字母大写
    private String upperHeadChar(String in){
        String head = in.substring(0,1);
        String out = head.toUpperCase()+in.substring(1,in.length());
        return out;
    }
}
